///
/// Random Variable Generator (RVG) Class
/// This class generates (Probability Distribution Name) distributed samples of a random variable
/// 
/// The Probability Density Functions (PDF) are
/// Continuos: Gaussian, Exponential, Pareto, Student's T, ...
/// Discrete: Poisson, Geometric, Bernoulli, Binomial, Generic Discrete PDF, ...
/// 
/// See LICENSE.TXT for licensing details
///

using System;
using System.Collections.Generic;
using System.Text;

namespace Dsp
{
    abstract public class RandomVariable
    {
        protected RNG rng;
        protected int count;

        public RNG Generator
        {
            get
            {
                return rng;
            }
            set
            {
                rng = value;
            }
        }

        abstract public double Next();

    }






    /// <summary>
    /// Gaussian Distribution computed with Polar method (Marsaglia & Bray, 1964)
    /// </summary>
    public class Gaussian : RandomVariable
    {
        private double sigma;
        private double mean;

        public double Mean  { get { return mean;  } set { mean = value;  } }
        public double Sigma { get { return sigma; } set { sigma = value; } }
        
        public Gaussian()
        {
            mean = 0;
            sigma = 1;
        }

        public override double Next()
        {
            // Polar Method
            double u1, u2;
            double x1;
            double v1, v2;
            double w;
            double y;

            do
            {
                u1 = rng.Next();
                u2 = rng.Next();
                v1 = 2 * u1 - 1;
                v2 = 2 * u2 - 1;
                w  = v1*v1 + v2*v2; 
            } 
            while (w > 1);

            y = Math.Sqrt(-2* Math.Log(w,Math.E)/w);


            x1 = v1 * y;

            // N(0, 1) transformation to N(mean, sigma)
            return (x1*sigma + mean);
        }

/*
        public double EvaluatePDF(double x)
        {
            // p(x) = \frac{1}{2\pi \sigma^2} exp(-\frac{(x-\mu)^2}{2\sigma^2})


        }
        */

    }

}



